<script setup lang="ts">
import {
  ref,
  toRef,
  computed,
  provide,
  onMounted,
  onBeforeUnmount,
  ComponentPublicInstance,
  onBeforeMount,
} from "vue"
import { FormItem } from "ant-design-vue"
import { useComputedBordered } from "@/composables/input-bordered"
import { useInjectCollapsibleFormContext } from "../collapsible-form/context"
import { formItemClientWidthKey } from "./context"
import { useInjectAppendFormItem } from "../rest-filter/context"
export interface Props {
  bordered?: boolean
  span?: number // 控制当前元素在表单中占的宽度
}

const props = withDefaults(defineProps<Props>(), {
  span: 1, // 元素默认的宽度是1
})

// 因为输入组件和FormItem只有一个要显示边框，所以需要取反
const { computedBordered: noneBordered } = useComputedBordered(props)

const computedClass = computed(() => {
  return {
    "form-item-bordered": !noneBordered.value,
    [`pc-col-span-${props.span}`]: true,
  }
})

const slots = defineSlots<InstanceType<typeof FormItem>["$slots"]>()

const formItem = ref<ComponentPublicInstance | null>(null)

const formItemClientWidth = ref<number>(0)

provide(formItemClientWidthKey, formItemClientWidth)

let resizeObserver: ResizeObserver | null = null

// 控制当前元素是否可见
const visible = ref<boolean>(true)

// 记录当前组件在列表中的索引
const selfIndex = ref<number>()

// 获取所有表单项
const formItems = useInjectCollapsibleFormContext()
const ifAppend = useInjectAppendFormItem()
function appendFormItem() {
  if (formItems) {
    // 获取当前元素的索引
    selfIndex.value = formItems.value.length
    if (!ifAppend.value) return
    // 插入当前元素的信息
    formItems?.value.push({
      span: toRef(props, "span"),
      visible: visible,
    })
  }
}

// TODO: 将添加和移除方法集成到CollapsibleFormContext中
// function removeSelf() {
//   if (selfIndex.value) {
//     formItems.value.splice(selfIndex.value, 1)
//   }
// }

onBeforeMount(appendFormItem)
// onBeforeUnmount(removeSelf)

onMounted(() => {
  if (formItem.value) {
    // 读取formItem宽度
    formItemClientWidth.value = formItem.value.$el.clientWidth

    // 监听formItem宽度
    resizeObserver = new ResizeObserver((entries) => {
      if (entries.length > 0) {
        formItemClientWidth.value = entries[0].target.clientWidth
      }
    })

    resizeObserver.observe(formItem.value.$el)
  }
})

onBeforeUnmount(() => {
  if (resizeObserver) {
    // 如果监听器存在，则关闭所有监听
    resizeObserver.disconnect()
  }
})
</script>

<template>
  <FormItem
    ref="formItem"
    v-show="visible"
    v-bind="$attrs"
    :class="computedClass"
  >
    <template v-for="(_, key) in slots" :key="key" #[key]="params">
      <slot :name="key" :key="key" v-bind="params"></slot>
    </template>
  </FormItem>
</template>

<style scoped>
.form-item-bordered {
  @apply pc-box-content;
  @apply pc-border pc-border-solid pc-border-[#c9cdd4];
  @apply pc-rounded-[6px];
  @apply pc-pl-[12px];
}
</style>
